#include "KeyRecommander.h"
#include "CacheManager.h"
#include "json.hpp"
#include <iostream>
#include <algorithm>

KeyRecommander::KeyRecommander(string &query, const TcpConnectionPtr &conn, Dictionary *dict)
: _queryWord(query), _conn(conn), _dict(dict){

}

KeyRecommander::~KeyRecommander(){

}

//执行查询操作
void KeyRecommander::execute(int thread_id){
    pair<set<int>, set<int>> result = queryIndexTable();
    statistic(result);
    response(thread_id);
}

//计算最小编辑距离需要的函数--------------------------------------------------

static size_t nBytesCode(const char ch){
    if(ch & (1 << 7)){
        int nBytes = 1;
        for(int idx = 0; idx != 6; ++idx){
            if(ch & (1 << (6 - idx))){
                ++nBytes;
            }
            else{
                break;
            }
        }
        return nBytes;
    }
    return 1;
}

static int triple_min(const int &a, const int &b, const int &c){
    return a < b ? (a < c ? a : c) : (b < c ? b : c);
}

static size_t length(const string &str){
    size_t ilen = 0;
    for(size_t idx = 0; idx != str.size(); ++idx){
        int nBytes = nBytesCode(str[idx]);
        idx += (nBytes - 1);
        ++ilen;
    }
    return ilen;
}

//计算最小编辑距离
static int editDistance(const string & lhs, const string &rhs)
{
    //计算最小编辑距离-包括处理中英文
    size_t lhs_len = length(lhs);
    size_t rhs_len = length(rhs);
    int editDist[lhs_len + 1][rhs_len + 1];
    for(size_t idx = 0; idx <= lhs_len; ++idx){
        editDist[idx][0] = idx;
    }
    for(size_t idx = 0; idx <= rhs_len; ++idx){
        editDist[0][idx] = idx;
    }
    string sublhs, subrhs;
    for(size_t dist_i = 1, lhs_idx = 0; dist_i <= lhs_len; ++dist_i, ++lhs_idx){
        size_t nBytes = nBytesCode(lhs[lhs_idx]);
        sublhs = lhs.substr(lhs_idx, nBytes);
        lhs_idx += (nBytes - 1);
        for(size_t dist_j = 1, rhs_idx = 0;
            dist_j <= rhs_len; ++dist_j, ++rhs_idx){
            nBytes = nBytesCode(rhs[rhs_idx]);
            subrhs = rhs.substr(rhs_idx, nBytes);
            rhs_idx += (nBytes - 1);
            if(sublhs == subrhs){
                editDist[dist_i][dist_j] = editDist[dist_i - 1][dist_j - 1];
            }
            else{
                editDist[dist_i][dist_j] =
                    triple_min(editDist[dist_i][dist_j - 1] + 1,
                               editDist[dist_i - 1][dist_j] + 1,
                               editDist[dist_i - 1][dist_j - 1] + 1);
            }
        }
    }
    return editDist[lhs_len][rhs_len];
}
//计算最小编辑距离需要的函数--------------------------------------------------

//查询词典
pair<set<int>, set<int>> KeyRecommander::queryIndexTable(){
    map<string, set<int>> &indexCn = _dict->getIndexTable();
    map<string, set<int>> &indexEn = _dict->getIndexTableEn();
    set<int> setUnionCn; //保存中文部分的查询结果
    set<int> setUnionEn; //保存英文部分的查询结果
    
    /* cout << "_queryWord: " << _queryWord << endl; */
    /* cout << "_queryWord.size: " << _queryWord.size() << endl; */
    
    for(size_t i = 0; i < _queryWord.size();){
        size_t size = nBytesCode(_queryWord[i]);
        string s = _queryWord.substr(i, size);
        /* cout << "size: " << size << ", " << "word: " << s << endl; */
        if(size != 1){
            set_union(setUnionCn.begin(), setUnionCn.end(),
                      indexCn[s].begin(), indexCn[s].end(), inserter(setUnionCn, setUnionCn.begin()));
        }
        else{
            set_union(setUnionEn.begin(), setUnionEn.end(),
                      indexEn[s].begin(), indexEn[s].end(), inserter(setUnionEn, setUnionEn.begin()));
        }
        i += size;
    }
    return {setUnionCn, setUnionEn};
}

//计算所有结果存入优先级队列
void KeyRecommander::statistic(pair<set<int>, set<int>> setPair){
    vector<pair<string, int>> &dictCn = _dict->getDict();
    for(auto &i: setPair.first){
        MyResult result;
        result._word = dictCn[i].first;
        result._freq = dictCn[i].second;
        result._dist = distance(result._word);
        _resultQue.push(result);
    }
    vector<pair<string, int>> &dictEn = _dict->getDictEn();
    for(auto &i: setPair.second){
        MyResult result;
        result._word = dictEn[i].first;
        result._freq = dictEn[i].second;
        result._dist = distance(result._word);
        _resultQue.push(result);
    }
}

//返回最小编辑距离
int KeyRecommander::distance(const string &rhs){
    return editDistance(_queryWord, rhs);
}

//向客户端发送回复
void KeyRecommander::response(int thread_id){
    vector<string> vec;
    int topN = TOP_N; //最多返回TOP_N个候选词
    while(!_resultQue.empty() && topN){
        string s = _resultQue.top()._word;
        vec.push_back(s);
        _resultQue.pop();
        topN--;
        /* cout << s << " "; */
    }
    /* cout << endl; */

    //将字符串数组封装为json
    using json = nlohmann::json;
    json j;
    j["data"] = vec;
    
    /* cout << j.dump() << endl; */
    /* cout << j.dump().size() << endl; */
    
    //向客户端发送回复
    _conn->sendInLoop(j.dump(), 1);
    
    //将这次查询的结果放入缓存
    CacheManager* instance = CacheManager::getInstance();
    {
        lock_guard<mutex> lock(instance->getMutex(thread_id));
        instance->getCache(thread_id).addElement(_queryWord, j.dump());
    }
    cout << "写入缓存成功\n";
}

